#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "cJSON.h"
#include "msg_queue_peer.h"
  #include "shmem.h"

static struct shm_param para;

union val_t
{ 
    int b_val;  //bool类型存储空间
    int i_val;   //整形值存储空间
    float f_val;  //浮点值存储空间
};

struct student
{
    char str[64]; //可以存放所有字符型
    int key;  //唯一键值
    int type;  //数据点类型
    int dev_type;  //数据点属于哪个设备，根据网关支持的设备自行定义
    union val_t old_val;  //变化上报后需要更新旧值
    union val_t new_val;  //从共享内存取出最新数据，放到new_val中
    int ret;  //默认为-1，采集成功后设置为0，采集失败再置-1
};

static int *total;  //指向共享内存中数据节点总个数
static struct student *node_arr;  //指向共享内存中节点缓存数组头

#define MAX_NODE 50  //最大支持学生数目
#define STD_NODE_LEN sizeof(struct student)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)



#define SERVER_PORT 8887
int acceptfd;
struct msgbuf
{   
    int mtype;
    char mdata[256];
};
struct msgbuf recv_buf;
void *handler_thread(void *arg)
{
    sleep(1);
     while (1)
    {
       // sleep(1);
        if(msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 0, 0) > 0)
        {//sleep(1);
             printf("recv from msga type = %d\n", recv_buf.mtype);
             printf("recv from msga data = %s\n", recv_buf.mdata);
            // printf("key=%d\n", node_arr[5].key);
            // for (int i = 0; i < 20; i++)
 //  {
      if(recv_buf.mtype==node_arr[14].key)
      {
        if(!strcmp(recv_buf.mdata,"ON"))
{

send(acceptfd,"FAN_ON",sizeof("FAN_ON"),0);
//sleep(1);
printf("风扇已开 = %s\n", recv_buf.mdata);
}

if(!strcmp(recv_buf.mdata,"OFF"))
{

send(acceptfd,"FAN_OFF",sizeof("FAN_OFF"),0);

printf("风扇已关 = %s\n", recv_buf.mdata);
}

      }


 if(recv_buf.mtype==node_arr[12].key)
      {
        if(!strcmp(recv_buf.mdata,"ON"))
{

send(acceptfd,"LED_ON",sizeof("LED_ON"),0);
//sleep(1);
printf("LED已开 = %s\n", recv_buf.mdata);
}

if(!strcmp(recv_buf.mdata,"OFF"))
{

send(acceptfd,"LED_OFF",sizeof("LED_OFF"),0);

printf("LED已关 = %s\n", recv_buf.mdata);
}

    }

if(recv_buf.mtype==node_arr[13].key)
      {
        if(!strcmp(recv_buf.mdata,"ON"))
{

send(acceptfd,"BEP_ON",sizeof("BEP_ON"),0);
//sleep(1);
printf("BEP已开 = %s\n", recv_buf.mdata);
}

if(!strcmp(recv_buf.mdata,"OFF"))
{

send(acceptfd,"BEP_OFF",sizeof("BEP_OFF"),0);

printf("BEP已关 = %s\n", recv_buf.mdata);
}

    }

        }
        else
        {
            perror("recv error:");
            return NULL;
        }

    }
    
   
    


}
int main()
{
   
 
  
   pthread_t tid;
    if (pthread_create(&tid, NULL, handler_thread, NULL) != 0)
    {
        perror("pthread create err");
        return -1;
    }
    printf("main\n");
   
    int ret = -1;

    ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);
    if(ret < 0)
    {
        return -1;
    }

    void *node_p = shm_getaddr(&para);
    if(node_p == NULL)
    {
        return -1;
    }

    //前4个字节存储实际的学生数目
    total = (int *)node_p;
    //后面空间存储数据点
    node_arr = (struct student *)(node_p + sizeof(int));


    
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("err.");
        return -1;
    }
    printf("sockfd:%d\n",sockfd);
    //2.绑定IP+port
    int opt=1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    struct sockaddr_in saddr; //身份结构定义
    saddr.sin_family=AF_INET; //填充第一成员变量--协议族
    saddr.sin_port=htons(SERVER_PORT);//填充端口号 8888
    saddr.sin_addr.s_addr=inet_addr("192.168.1.51");//填充IP地址
    socklen_t addrlen=sizeof(saddr);
    if(bind(sockfd,(struct sockaddr *)&saddr,addrlen) == -1)
    {
        perror("err.");
        return -1;
    }
    printf("bind ok\n");
    //3.监听 将主动套接字变成被动套接字  
    listen(sockfd,6);
    printf("正在等待连接...\n");
    //4.accept,生成新的套接字--用于通信,当没有连接可建立的时候，阻塞
     acceptfd= accept(sockfd,NULL,NULL);
    printf("连接已建立...\n");
    //5.发送
    char buf[1024]={0};
    float temp=0;
    float humi=0;
    while (1)
    {
        int ret=recv(acceptfd,buf,1024,0);

       
        if(ret == 0)
        {
            printf("client quit...\n");
            break;
        }
        else if(ret > 0)
        {
           
           cJSON *aaa=cJSON_Parse(buf);

if(aaa == NULL)
    {
        printf("parse err\n");
        return -1;
    }
cJSON *eee=cJSON_GetObjectItem(aaa,"light");
cJSON *ddd=cJSON_GetObjectItem(aaa,"temp");
cJSON *bbb=cJSON_GetObjectItem(aaa,"hum");
cJSON *fff=cJSON_GetObjectItem(aaa,"vbat");
           
      node_arr[11].new_val.f_val=eee->valueint;
      node_arr[9].new_val.f_val=ddd->valuedouble;
      node_arr[10].new_val.f_val=bbb->valuedouble;
      node_arr[12].new_val.f_val=fff->valuedouble;
           
           printf("temperature:%.2f, humidity:%.2f\n",node_arr[9].new_val.f_val=ddd->valuedouble,node_arr[10].new_val.f_val);
            printf("recv:%s\n",buf);
           // sscanf(buf,"%f/%f",&temp,&humi);
           // printf("temperature:%.2f, humidity:%.2f\n",temp,humi);

            // if (node_arr[9].new_val.f_val > 27)
            // {
            //     send(acceptfd,"FAN_ON",sizeof("FAN_ON"),0);
            // }
            // else if (node_arr[9].new_val.f_val < 27)
            // {
            //     send(acceptfd,"FAN_OFF",sizeof("FAN_OFF"),0);
            // }
            // if (node_arr[10].new_val.f_val > 50)
            // {
            //     send(acceptfd,"LED_ON",sizeof("LD1_ON"),0);
            // }
            // else if (node_arr[10].new_val.f_val < 48)
            // {
            //     send(acceptfd,"LED_OFF",sizeof("LD1_OFF"),0);
            // }
            memset(buf,0,1024);
        }
    }
    return 0;
}